package mysql

import (
	"fmt"
	"gitee.com/lipore/plume/db_gorm/gen/code"
	"gitee.com/lipore/plume/db_gorm/gen/spec"
	"strings"
	"text/template"
)

type repositoryMethodData struct {
	Receiver code.Param
	Spec     spec.MethodSpec
}

func receiverToCode(p code.Param) string {
	if pt, ok := p.Type.(code.PointerType); ok {
		return fmt.Sprintf("%s %s", p.Name, pt.Code())
	}
	panic("receiver type should be pointer")
}

func paramToCode(p code.Param) string {
	return fmt.Sprintf("%s %s", p.Name, p.Type.Code())
}

func paramsToCode(params []code.Param) string {
	strParams := make([]string, len(params))
	for i, p := range params {
		strParams[i] = paramToCode(p)
	}
	return strings.Join(strParams, ",")
}

func returnsToCode(returns []code.Type) string {
	if len(returns) == 0 {
		return ""
	}
	if len(returns) == 1 {
		return returns[0].Code()
	}
	strRets := make([]string, len(returns))
	for i, r := range returns {
		strRets[i] = typeToCode(r)
	}
	return fmt.Sprintf("(%s)", strings.Join(strRets, ","))
}
func typeToCode(t code.Type) string {
	return t.Code()
}

var repositoryMethodTemplate = `{{define "repositoryMethod"}}func ({{receiverToCode .Receiver}}) {{.Spec.Name}}({{paramsToCode .Spec.Params}}) {{returnsToCode .Spec.Returns}}{{end}}`

func renderRepositoryMethod(tmpl *template.Template) (*template.Template, error) {
	funcMap := template.FuncMap{"paramsToCode": paramsToCode, "paramToCode": paramToCode, "returnsToCode": returnsToCode, "typeToCode": typeToCode, "receiverToCode": receiverToCode}
	tmpl, err := tmpl.Funcs(funcMap).Parse(repositoryMethodTemplate)
	if err != nil {
		return nil, err
	}
	return tmpl, err
}

type intOrBoolReturnData struct {
	IntReturn bool
}

var errorHandleReturnTemplate = `{{define "errorReturnStmt" -}}
{{- if .IntReturn }}
		return 0, err
{{- else }}
		return false, err
{{- end }}
{{end}}`

var intOrBoolReturnTemplate = `{{define "returnStmt" -}}
{{- if .IntReturn }}
    return result.RowsAffected, nil
{{- else }}
	return result.RowsAffected>0, nil
{{- end }}{{end}}`

func renderReturnStmt(tmpl *template.Template) (*template.Template, error) {
	tmpl, err := tmpl.Parse(errorHandleReturnTemplate)
	if err != nil {
		return nil, err
	}
	return tmpl.Parse(intOrBoolReturnTemplate)
}
